// --- START OF FILE PlaceableObject.cs ---

using System.Collections.Generic;
using UnityEngine;

namespace PlaceSystem
{
    /// <summary>
    /// 附加到所有可以被放置的物体上（如家具、装饰品）。
    /// </summary>
    public class PlaceableObject : MonoBehaviour
    {
        [Header("用于计算占地范围的碰撞体")]
        [Tooltip("这个碰撞体定义了物体的占地面积，用于检测重叠。")]
        public List<BoxCollider> colliders;

        [Header("可放置道具上可能存在的放置表面")]
        public List<PlacementSurface> playableSurfaces = new();

        [Header("当前物体碰撞层")]
        public int layer;

        // 优化：使用字典来存储每个渲染器的原始材质数组，键是渲染器，值是其对应的材质数组。
        // 这样做可以避免在恢复材质时重新创建数组，提升性能。
        private readonly Dictionary<Renderer, Material[]> _originalMaterials = new();
        private readonly Dictionary<Renderer, Material[]> _previewMaterials = new();

        private void Awake()
        {
            // 初始化，获取所有子物体的渲染器和它们的原始材质
            // 使用GetComponentsInChildren(true, ...) 来确保即使是非激活状态的子物体也能被获取到
            var renderers = GetComponentsInChildren<Renderer>(true);
            foreach (var r in renderers)
            {
                // 将每个渲染器的 sharedMaterials 数组（这是材质的引用）直接存入字典
                _originalMaterials.Add(r, r.sharedMaterials);
                _previewMaterials.Add(r, new Material[r.sharedMaterials.Length]);
            }
        }

        private void OnEnable()
        {
            // 当物体启用时，向控制器注册自己
            PlaceSystemController.EnablePlaceableObject(this);
        }

        private void OnDisable()
        {
            // 当物体禁用或销毁时，从控制器注销自己
            PlaceSystemController.DisablePlaceableObject(this);
        }

        /// <summary>
        /// 注册
        /// </summary>
        /// <param name="map"></param>
        public void Register(Dictionary<Collider, PlaceableObject> map)
        {
            if (colliders == null || colliders.Count == 0) return;
            EnableColliders();
            foreach (BoxCollider collider in colliders)
            {
                map.TryAdd(collider, this);
            }
        }

        /// <summary>
        /// 移除注册
        /// </summary>
        /// <param name="map"></param>
        public void Unregister(Dictionary<Collider, PlaceableObject> map)
        {
            if (colliders == null || colliders.Count == 0) return;
            DisableColliders();
            foreach (BoxCollider collider in colliders)
            {
                map.Remove(collider);
            }
        }

        /// <summary>
        /// 检查当前物体是否在给定的层重叠
        /// </summary>
        /// <param name="layerMask"></param>
        /// <returns></returns>
        public bool CheckBox(int layerMask)
        {
            if (colliders == null) return true;
            if (colliders.Count == 0) return true;
            foreach (BoxCollider collider in colliders)
            {
                Transform current = collider.transform;
                // 计算用于检测的盒体的世界坐标中心点
                Vector3 worldCenter = current.TransformPoint(collider.center);
                // 计算考虑了缩放的盒体大小
                Vector3 scaledSize = Vector3.Scale(collider.size, current.lossyScale);
                // 使用 CheckBox 进行重叠检测，只检测 layerMask 上的物体
                bool hasSpace = Physics.CheckBox(worldCenter, scaledSize * 0.5f, current.rotation, layerMask);
                if (!hasSpace) return true;
            }
            return false;
        }

        /// <summary>
        /// 启用碰撞器
        /// </summary>
        public void EnableColliders()
        {
            if (colliders == null || colliders.Count == 0) return;
            foreach (BoxCollider collider in colliders)
            {
                collider.gameObject.layer = layer;
            }
        }

        /// <summary>
        /// 禁用碰撞器
        /// </summary>
        public void DisableColliders()
        {
            if (colliders == null || colliders.Count == 0) return;
            foreach (BoxCollider collider in colliders)
            {
                collider.gameObject.layer = 2;
            }
        }


        /// <summary>
        /// 开始拖拽
        /// </summary>
        public void BeginDrag()
        {
            DisableColliders();
            if (playableSurfaces != null && playableSurfaces.Count > 0)
            {
                foreach (PlacementSurface surface in playableSurfaces)
                {
                    surface.enabled = false;
                }
            }
        }

        /// <summary>
        /// 结束拖拽
        /// </summary>
        public void EndDrag()
        {
            EnableColliders();
            if (playableSurfaces != null && playableSurfaces.Count > 0)
            {
                foreach (PlacementSurface surface in playableSurfaces)
                {
                    surface.enabled = true;
                }
            }
        }

        /// <summary>
        /// 将物体材质设置为预览模式
        /// </summary>
        public void SetPreviewMaterial(Material previewMaterial)
        {
            foreach (var pair in _previewMaterials)
            {
                var mats = pair.Value;
                for (int i = 0; i < mats.Length; i++)
                {
                    mats[i] = previewMaterial;
                }
                pair.Key.materials = mats;
            }
        }

        /// <summary>
        /// 恢复物体的原始材质 (已优化)
        /// </summary>
        public void RestoreOriginalMaterials()
        {
            // 优化：直接从字典中取出预先存储好的材质数组进行恢复。
            // 这个操作没有创建任何新的数组，也无需复杂的索引计算，性能更好。
            foreach (var pair in _originalMaterials)
            {
                // pair.Key 是 Renderer, pair.Value 是对应的 Material[]
                pair.Key.materials = pair.Value;
            }
        }
    }
}
// --- END OF FILE PlaceableObject.cs ---